package org.jugile.util;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import org.jugile.util.Jugile;
import org.jugile.util.Node;

/*

Copyright (C) 2007-2014 Jukka Rahkonen  email: jukka.rahkonen@iki.fi

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*/

/**
 * "All things were made by him; and without him was not any thing made that was made.
 *  In him was life; and the life was the light of men. And the light shineth in darkness; 
 *  and the darkness comprehended it not." (John 1:3-5)
 * 
 * ===========
 * 
 * Very simple Soap client. Why it should be any more complicated than this 100 lines of java?
 * @author jukka.rahkonen@iki.fi
 */
public class Soap extends Jugile {

	private String url;
	private String xmlns;
	private String xmlnsUrl;
	
	public Soap(String url, String xmlns, String xmlnsUrl) {
		this.url = url;
		this.xmlns = xmlns;
		this.xmlnsUrl = xmlnsUrl;
	}
	
	private String userid;
	private String passwd;
	private String useridpasswdBase64;
	
	public void setLogin(String userid, String passwd) {
		this.userid = userid;
		this.passwd = passwd;
		useridpasswdBase64 = Base64.encode(userid + ":" + passwd);
	}
	public void setBase64(String v) { useridpasswdBase64 = v; }
	
	public String soap(String action, Node data) {
		Node n = new Node("soapenv:Envelope")
			.attr("xmlns:soapenv","http://schemas.xmlsoap.org/soap/envelope/")
			.attr("xmlns:"+xmlns,xmlnsUrl);
		Node header = n.add("soapenv:Header");
		Node body = n.add("soapenv:Body");

		Node d2 = copy(data);
		d2.setName(xmlns+":"+action);
		body.add(d2);
		String soap = n.render();
		print("soap:\n"+ soap);
		return soap(action, soap);
	}

	private Node copy(Node n) {
		Node n2 = new Node(xmlns+":"+n.name());
		n2.value(n.value());
		for (Node c : n.children()) n2.add(copy(c));
		return n2;
	}
	
	public String soap(String action, String data) {
		BufferedReader in = null;
		OutputStreamWriter out = null;
		try {
			URL u = new URL(url);
			HttpURLConnection uc = (HttpURLConnection)u.openConnection();
			uc.setRequestMethod("POST");
			uc.setRequestProperty("Content-Type","text/xml;charset=utf-8");
			uc.setRequestProperty("SOAPAction",xmlnsUrl+"/"+action);
			if (!empty(userid)) {
				uc.setRequestProperty("Authorization","Basic "+useridpasswdBase64);
			}

			uc.setDoOutput(true);
			out = new OutputStreamWriter(uc.getOutputStream());
			out.write(data);
			out.close(); out = null;
			if (uc.getResponseCode() != 200) {
				fail("STATUS:" + uc.getResponseCode() + " " + uc.getResponseMessage());
			}
            //get result
            in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
			StringBuilder response = new StringBuilder();
			String inputLine;
			while ((inputLine = in.readLine()) != null) 
				response.append(inputLine + "\n");
			in.close(); in = null;
			return response.toString();
		} catch (Exception e) { 
			fail(e); 
		} finally {
			if (in != null) try { in.close(); } catch(Exception e) { }
			if (out != null) try { out.close(); } catch(Exception e) { }
		}
		return null;
	}

	public static void main(String args[]) throws Exception {
		//print("WSDL:\n" + httpGet("https://tonedev.portal.tieto.com/u_tcs_relation_queue.do?WSDL"));

		Soap s = new Soap("http://www.webservicex.com/globalweather.asmx",
				"web","http://www.webserviceX.NET");

		Node n = new Node("data");
		n.add("CityName","Helsinki-Malmi");
		n.add("CountryName","Finland");
		print("n:\n" + n.render());
		
		String res = s.soap("GetWeather",n);
		print("res:\n" + res);
		
		Node xml = Jugile.parseXmlString(res);
		print("xml:\n" + xml.render());
	}
	
}
